/*
    Project:        Home Power Control
    File:           HPCValue.cpp
    Author:         christian@karunamusic.at
    Date:           12.2014
    Description:    A value class for all numeric types for use with the sensors.
 */

#include <stdexcept>
#include <sstream>
#include "HPCValue.h"

HPCValue::HPCValue()
    : m_Type(undefined)
{
    m_Timestamp = dateTime();
    m_Val.asDouble = (double)0.0;
}

HPCValue::HPCValue( const char* val, ValueType vt )
    : m_Type(vt)
{
    m_Timestamp = dateTime();
    std::string s = val;
    operator= (s);
}

HPCValue::HPCValue( HPCValue& ref )
{
    *this = ref;
}

HPCValue::~HPCValue()
{
}

HPCValue::operator std::string() const
{
    std::stringstream ret;

    switch ( m_Type )
    {
        case Boolean:
            ret << m_Val.asBoolean;
        break;
        case SignedChar:
            ret << m_Val.asSignedChar;
        break;
        case UnsignedChar:
            ret << m_Val.asUnsignedChar;
        break;
        case SignedInt:
            ret << m_Val.asSignedInt;
        break;
        case UnsignedInt:
            ret << m_Val.asUnsignedInt;
        break;
        case SignedLong:
            ret << m_Val.asSignedLong;
        break;
        case UnsignedLong:
            ret << m_Val.asUnsignedLong;
        break;
        case Float:
            ret << m_Val.asFloat;
        break;
        case Double:
            ret << m_Val.asDouble;
        break;
        default:
            ret << "undefined";
        break;
    }

    return ret.str();
}

HPCValue& HPCValue::operator= (bool v)
{
    m_Val.asBoolean = v;
    if ( m_Type == undefined )
        m_Type = Boolean;
    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (char v)
{
    m_Val.asSignedChar = v;
    if ( m_Type == undefined )
        m_Type = SignedChar;
    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (unsigned char v)
{
    m_Val.asUnsignedChar = v;
    if ( m_Type == undefined )
        m_Type = UnsignedChar;
    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (int v)
{
    m_Val.asSignedInt = v;
    if ( m_Type == undefined )
        m_Type = SignedInt;
    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (unsigned int v)
{
    m_Val.asUnsignedInt = v;
    if ( m_Type == undefined )
        m_Type = UnsignedInt;
    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (long v)
{
    m_Val.asSignedLong = v;
    if ( m_Type == undefined )
        m_Type = SignedLong;
    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (unsigned long v)
{
    m_Val.asUnsignedLong = v;
    if ( m_Type == undefined )
        m_Type = UnsignedLong;
    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (float v)
{
    m_Val.asFloat = v;
    if ( m_Type == undefined )
        m_Type = Float;
    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (double v)
{
    m_Val.asDouble = v;
    if ( m_Type == undefined )
        m_Type = Double;
    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (const std::string& v)
{
    std::istringstream is(v);
    switch ( m_Type )
    {
        case Boolean:
            is >> m_Val.asBoolean;
        break;
        case SignedChar:
            is >> m_Val.asSignedChar;
        break;
        case UnsignedChar:
            is >> m_Val.asUnsignedChar;
        break;
        case SignedInt:
            is >> m_Val.asSignedInt;
        break;
        case UnsignedInt:
            is >> m_Val.asUnsignedInt;
        break;
        case SignedLong:
            is >> m_Val.asSignedLong;
        break;
        case UnsignedLong:
            is >> m_Val.asUnsignedLong;
        break;
        case Float:
            is >> m_Val.asFloat;
        break;
        case Double:
            is >> m_Val.asDouble;
        break;
        default:
            throw std::runtime_error( "HPCValue=: type not defined" );
        break;
    }

    m_Timestamp = dateTime();
    return *this;
}

HPCValue& HPCValue::operator= (const HPCValue& v)
{
    if ( m_Type == undefined )
        m_Type = v.m_Type;
    m_Val = v.m_Val;
    m_Timestamp = v.m_Timestamp;
    return *this;
}

std::string HPCValue::dateTime()
{
    time_t now = time(0);
    struct tm tstruct;
    char buf[80];

    tstruct = *localtime( &now );
    strftime( buf,sizeof(buf),"%Y-%m-%d %X",&tstruct );

    return buf;
}
